<!--表格-->
<template>
	<zh-card :title="title" :shadow="shadow" :mode="mode" :body-style="{ borderStyle: 'none' }">
		<template #header>
			<slot name="header">
				<div class="card-header">
					<span style="font-weight: 500" :style="{ fontSize: fontSize }">{{ title }}</span>
					<div>
						<slot name="header_button"> </slot>
					</div>
				</div>
			</slot>
		</template>
		<slot name="query"> </slot>
		<vxe-grid
			v-if="type === 'default'"
			ref="zhGrid"
			:id="id"
			v-bind="attrs"
			class="my-xtable-element"
			:auto-resize="autoResize"
			:sync-resize="syncResize"
			:border="border"
			:columns="tableColums"
			:data="tableData"
			:stripe="stripe"
			:size="mySize"
			:loading="loading"
			:align="align"
			:height="height"
			:max-height="maxHeight"
			:showFooter="showFooter"
			:checkbox-config="allCheckboxConfig"
			:radio-config="allRadioConfig"
			:round="round"
			:footer-align="footerAlign"
			:header-align="headerAlign"
			:edit-rules="editRules"
			:show-header="showHeader"
			:showOverflow="showOverflow"
			:showHeaderOverflow="showHeaderOverflow"
			:show-footer-overflow="showFooterOverflow"
			:row-config="rowId ? Object.assign(rowConfig, { keyField: rowId }) : rowConfig"
			:column-config="columnConfig"
			:header-cell-class-name="headerCellClassName"
			:row-class-name="rowClassName"
			:cell-class-name="cellClassName"
			:header-cell-style="headerCellStyle"
			:row-style="rowStyle"
			:cell-style="cellStyle"
			:edit-config="
				disabled
					? {}
					: editConfig
					? editConfig
					: { trigger: 'click', mode: 'cell', showStatus: true, autoClear: false, activeMethod: activeRowMethod }
			"
			:tooltip-config="tooltipConfig"
			:toolbar-config="toolbarConfig"
			:keep-source="keepSource"
			:sort-config="sortConfig"
			@checkbox-change="checkboxChange"
      @cell-dblclick="cellDblclick"
      @checkbox-all="checkboxAll"
			@sort-change="sortChange"
			:export-config="exportConfig"
		>
			<template #[item]="data" v-for="item in Object.keys($slots)">
				<slot :name="item" v-bind="data || {}"></slot>
			</template>
			<template #dragBtn>
				<SvgIcon class="table-drag-btn" name="ele-Rank" />
			</template>
			<template #dragTip>
				<el-tooltip effect="dark" content="按住后可上下拖动" placement="top">
					<SvgIcon name="ele-InfoFilled" />
				</el-tooltip>
			</template>
		</vxe-grid>
		<vxe-grid
			v-if="type === 'paging'"
			ref="zhGrid"
			:id="id"
			v-bind="attrs"
			class="my-xtable-element"
			:auto-resize="autoResize"
			:sync-resize="syncResize"
			:border="border"
			:stripe="stripe"
			:size="mySize"
			:loading="loading"
			:align="align"
			:height="height"
			:showFooter="showFooter"
			:checkbox-config="allCheckboxConfig"
			:radio-config="allRadioConfig"
			:columns="tableColums"
			:data="tableData"
			:round="round"
			:header-align="headerAlign"
			:footer-align="footerAlign"
			:edit-rules="editRules"
			:show-header="showHeader"
			:showOverflow="showOverflow"
			:showHeaderOverflow="showHeaderOverflow"
			:show-footer-overflow="showFooterOverflow"
			:row-config="
				rowId
					? Object.assign(rowConfig, { keyField: rowId })
					: Object.assign({ useKey: false, keyField: '_X_ROW_KEY', isCurrent: true, isHover: true, height: undefined }, rowConfig)
			"
			:column-config="columnConfig"
			:header-cell-class-name="headerCellClassName"
			:row-class-name="rowClassName"
			:cell-class-name="cellClassName"
			:header-cell-style="headerCellStyle"
			:row-style="rowStyle"
			:cell-style="cellStyle"
			:keep-source="keepSource"
			:edit-config="
				disabled
					? {}
					: editConfig
					? editConfig
					: { trigger: 'click', mode: 'cell', showStatus: true, autoClear: false, activeMethod: activeRowMethod }
			"
			:seq-config="{ startIndex: (tablePage.currentPage - 1) * tablePage.pageSize }"
			:tooltip-config="tooltipConfig"
			:toolbar-config="toolbarConfig"
			:sort-config="sortConfig"
			@checkbox-change="checkboxChange"
			@checkbox-all="checkboxAll"
			@sort-change="sortChange"
			:export-config="exportConfig"
		>
			<template #pager>
				<vxe-pager
					:layouts="layouts"
					v-model:current-page="tablePage.currentPage"
					v-model:page-size="tablePage.pageSize"
					:total="tablePage.total"
					:page-sizes="pagerConfig.pageSizes"
					@page-change="handlePageChange"
				>
					<template v-if="showPageLeft" #left>
						<span class="page-left">
							<el-checkbox :indeterminate="isIndeterminate" v-model="isAllChecked" @change="changeAllEvent">
								<span>全表全选</span>
								<span style="padding-left: 10px">已选中 {{ count }} 条</span>
							</el-checkbox>
						</span>
					</template>
				</vxe-pager>
			</template>
			<template #[item]="data" v-for="item in Object.keys($slots)">
				<slot :name="item" v-bind="data || {}"></slot>
			</template>
		</vxe-grid>
	</zh-card>
</template>
<script lang="ts">
import { uuid } from '@/utils/util';
import { VXETable, VxeGridInstance } from 'vxe-table';
import XEUtils from 'xe-utils';
import extendTableMethods from './gridMethods';
import Sortable from 'sortablejs';
export default defineComponent({
	name: 'zh-table',
	inheritAttrs: false,
	props: {
		//是否加密
		cryptoEnabled: {
			type: Boolean,
			default: false,
		},
		//是否脱敏
		desensitizeFlag: {
			type: Boolean,
			default: false,
		},
		//是否防重复提交
		repeatEnabled: {
			type: Boolean,
			default: false,
		},
		mode: {
			type: String,
			default: 'primary-light',
		},
		//接口超时时间
		timeout: Number,
		//默认 default paging 分页
		type: {
			type: String,
			default: 'paging',
		},
		//是否可拖拽
		draggable: {
			type: Boolean,
			default: false,
		},
		//标题
		title: {
			type: String,
			default: null,
		},
		//是否可编辑
		disabled: {
			type: Boolean,
			default: true,
		},
		disabledList: {
			type: Array,
			default: () => {
				return [];
			},
		},
		//是否淡颜色
		light: {
			type: Boolean,
			default: true,
		},
		//设置阴影显示时机 always / hover / never
		shadow: {
			type: String,
			default: 'hover',
		},
		//请求数据的url
		url: {
			type: String,
			default: '',
		},
		//请求功能编号
		funcCode: {
			type: String,
			default: '',
		},
		columns: {
			type: Array,
			default: () => {
				return [];
			},
			require: true,
		},
		data: {
			type: Array,
			default: () => {
				return null;
			},
		},
		//是否带有边框default（默认）, full（完整边框）, outer（外边框）, inner（内边框）, none（无边框）
		border: {
			type: [Boolean, String],
			default: true,
		},
		// 自动监听父元素的变化去重新计算表格（对于父元素可能存在动态变化、显示隐藏的容器中、列宽异常等场景中的可能会用到）boolean
		autoResize: {
			type: Boolean,
			default: true,
		},
		// 自动跟随某个属性的变化去重新计算表格，和手动调用 recalculate 方法是一样的效果（对于通过某个属性来控制显示/隐藏切换时可能会用到）boolean | string | number
		syncResize: {
			type: [Boolean, String, Number],
			default: undefined,
		},
		//是否带有斑马纹（需要注意的是，在可编辑表格场景下，临时插入的数据不会有斑马纹样式）
		stripe: {
			type: Boolean,
			default: true,
		},
		//表格的尺寸medium, small, mini
		size: {
			type: String,
		},
		exportConfig: {
			type: Object,
			default: () => {
				return {
					// 默认选中类型
					type: 'xml',
					// 自定义类型
					types: ['csv', 'html', 'xml', 'txt'],
				};
			},
		},
		//所有的列对齐方式 left（左对齐）, center（居中对齐）, right（右对齐）
		align: {
			type: String,
			default: 'center',
		},
		//表格的高度；支持铺满父容器或者固定高度，如果设置 auto 为铺满父容器（如果设置为 auto，则必须确保存在父节点且不允许存在相邻元素）auto, %, px
		height: {
			type: [Number, String],
			default: window.innerHeight - 180 + 'px',
		},
		// 表格的最大高度 %, px
		maxHeight: {
			type: [Number, String],
			default: undefined,
		},
		//是否为圆角边框
		round: {
			type: Boolean,
			default: false,
		},
		//所有的表头列的对齐方式left（左对齐）, center（居中对齐）, right（右对齐）
		headerAlign: {
			type: String,
			default: 'center',
		},
		//left（左对齐）, center（居中对齐）, right（右对齐）
		footerAlign: {
			type: String,
			default: 'center',
		},
		//鼠标移到行是否要高亮显示
		highlightHoverRow: {
			type: Boolean,
			default: true,
		},
		//是否要高亮当前行
		highlightCurrentRow: {
			type: Boolean,
			default: true,
		},
		//鼠标移到列是否要高亮显示
		highlightHoverColumn: {
			type: Boolean,
			default: true,
		},
		//是否要高亮当前列
		highlightCurrentColumn: {
			type: Boolean,
			default: true,
		},
		//是否显示表头
		showHeader: {
			type: Boolean,
			default: true,
		},
		//设置所有内容过长时显示为省略号（如果是固定列建议设置该值，提升渲染速度） ellipsis（只显示省略号）,title（并且显示为原生 title）,tooltip（并且显示为 tooltip 提示）
		showOverflow: {
			type: [Boolean, String],
			default: true,
		},
		//设置表头所有内容过长时显示为省略号 ellipsis（只显示省略号）,title（并且显示为原生 title）,tooltip（并且显示为 tooltip 提示）
		showHeaderOverflow: {
			type: [Boolean, String],
			default: true,
		},
		//设置表尾所有内容过长时显示为省略号ellipsis（只显示省略号）,title（并且显示为原生 title）,tooltip（并且显示为 tooltip 提示）
		showFooterOverflow: {
			type: [Boolean, String],
			default: true,
		},
		//自定义行数据唯一主键的字段名（行数据必须要有唯一主键，默认自动生成）
		rowId: {
			type: String,
			default: null,
		},
		rowConfig: {
			type: Object,
			default: () => {
				return { useKey: false, keyField: '_X_ROW_KEY', isCurrent: true, isHover: true, height: undefined };
			},
		},
		columnConfig: {
			type: Object,
			default: () => {
				return { useKey: false, isCurrent: true, isHover: true, resizable: true, width: undefined, minWidth: undefined };
			},
		},
		//保持原始值的状态，被某些功能所依赖，比如编辑状态、还原数据等（开启后影响性能，具体取决于数据量）
		keepSource: {
			type: Boolean,
			default: true,
		},
		editConfig: {
			type: Object,
			default: () => {
				return undefined;
			},
		},
		showFooter: {
			type: Boolean,
			default: false,
		},
		pagerConfig: {
			type: Object,
			default: () => {
				return {
					pageSize: 20,
					pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000],
				};
			},
		},
		// 单选框配置项
		radioConfig: {
			type: Object,
			default: () => {
				return undefined;
			},
		},
		// 复选框配置项
		checkboxConfig: {
			type: Object,
			default: () => {
				return undefined;
			},
		},
		editRules: {
			type: Object,
			default: () => {
				return {};
			},
		},
		tooltipConfig: {
			type: Object,
			default: () => {
				return { showAll: false, theme: 'light', enterable: false, leaveDelay: 300 };
			},
		},
		toolbarConfig: {
			type: Object,
			default: () => {
				return null;
			},
		},
		sortConfig: {
			type: Object,
			default: () => {
				return {
					trigger: 'cell',
					remote: true,
				};
			},
		},
		orderByList: {
			type: Array,
			default: () => {
				return [];
			},
		},
		layouts: {
			type: Array,
			default: () => {
				return ['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'PageCount', 'Total'];
			},
		},
		headerCellClassName: {
			type: [Function, String],
			default: 'table-header',
		},
		rowClassName: {
			type: [Function, String],
		},
		cellClassName: {
			type: [Function, String],
		},
		headerCellStyle: {
			type: Function,
		},
		rowStyle: {
			type: Function,
		},
		cellStyle: {
			type: Function,
		},
		extend: {
			// 扩展属性，对象形式，存放组件的扩展属性
			type: Object,
			default: () => {
				return {};
			},
		},
	},
	setup(props, context) {
		const zhGrid = ref({} as VxeGridInstance);
		const that: any = getCurrentInstance();
		const fontSize = ref('14px');
		const attrs = computed(() => {
			return Object.assign(props.extend, context.attrs);
		});

		const allCheckboxConfig = computed(() => {
			return { ...props.checkboxConfig, reserve: true, highlight: true, checkMethod: onCheckMethod };
		});

		const allRadioConfig = computed(() => {
			return { ...props.radioConfig, reserve: true, highlight: true, checkMethod: onCheckMethod };
		});

		const state = reactive({
			id: uuid(),
			loading: false,
			tablePage: {
				total: 0,
				pageNum: 1,
				currentPage: 1,
				pageSize: props.pagerConfig.pageSize ? props.pagerConfig.pageSize : 20,
			},
			theUrl: props.url,
			tableData: [] as any,
			allData: [] as any,
			queryParam: {} as any,
			apiTimeout: props.timeout,
			tableColums: [],
			isAllChecked: false,
			isIndeterminate: false,
			selectRecords: [] as any,
			selectRow: null,
			count: 0,
			showPageLeft: false,
			slotList: [],
			orderList: props.orderByList,
			mySize: props.size,
		});
		if (!state.mySize) {
			let globalComponentSize = $store.theme.globalComponentSize;
			if (globalComponentSize === 'small') {
				state.mySize = 'mini';
				fontSize.value = '12px';
			} else if (globalComponentSize === 'default') {
				state.mySize = 'small';
				fontSize.value = '14px';
			} else {
				state.mySize = 'medium';
				fontSize.value = '16px';
			}
		}

		watch(
			() => props.data,
			() => {
				if (props.data) {
					nextTick(() => {
						setData(props.data);
					});
				}
			},
			{
				deep: true,
			}
		);

		watch(
			() => props.columns,
			() => {
				getTableColum();
				if (props.columns && props.columns.length > 0) {
					setShowPageLeft(props.columns);
				} else {
					state.showPageLeft = false;
				}
			},
			{
				deep: true,
			}
		);
		watch(
			() => props.disabledList,
			() => {
				setDisabledList();
			},
			{
				deep: true,
			}
		);

		if (props.data) {
			setData(props.data);
		}
		if (props.columns) {
			getTableColum();
			setShowPageLeft(props.columns);
		}
		function getTableColum() {
			let tableColums = [] as any;
			if (props.draggable) {
				let slots = { default: 'dragBtn', header: 'dragTip' };
				let param = { width: 50, slots: slots } as any;
				tableColums.push(param);
			}

			tableColums.push(...props.columns);
			state.tableColums = tableColums;
		}
		function setShowPageLeft(list: any) {
			let size = list.length;
			for (let i = 0; i < size; i++) {
				let item = list[i];
				if (item.type === 'checkbox') {
					state.showPageLeft = true;
					break;
				}
			}
		}
		function setDisabledList() {
			if (state.tableData && state.tableData.length > 0) {
				state.tableData.forEach((item) => {
					item.disabled = checkDisabled(item);
				});
			}
		}
		const checkDisabled = (row) => {
			if(row.disabled){
				return true;
			}
			let list = props.disabledList;
			if (list && list.length > 0) {
				let rowId = props.rowId || props.rowConfig.keyField;
				let hasList = list.filter((item) => item[rowId] === row[rowId]);
				if (hasList && hasList.length > 0) {
					return true;
				}
			}
			return false;
		};
		function setData(data: any) {
			state.allData = data;
			//zhGrid.value.clearCheckboxReserve()
			//zhGrid.value.clearRadioReserve()
			if (props.type === 'paging') {
				setTableList();
			} else {
				state.tableData = data;
			}
		}
		function setTableData(data: any) {
			state.tableData = data;
		}
		function handlePageChange({ currentPage, pageSize }: any) {
			pageChange(currentPage, pageSize).then(function () {
				if (state.isAllChecked) {
					zhGrid.value.setAllCheckboxRow(state.isAllChecked);
				}
				setTimeout(() => {
					zhGrid.value.scrollTo(0, 0);
				}, 100);
			});
		}
		function pageChange(currentPage: any, pageSize: any) {
			return new Promise((resolve) => {
				state.tablePage.pageNum = currentPage;
				state.tablePage.currentPage = currentPage;
				state.tablePage.pageSize = pageSize;
				if (props.url || props.funcCode) {
					findTableList().then((res) => {
						resolve(res);
					});
				} else {
					setTableList().then((res) => {
						resolve(res);
					});
				}
			});
		}
		function query(queryParam: any, timeout: any) {
			state.tablePage.pageNum = 1;
			state.tablePage.currentPage = 1;
			if (queryParam) {
				state.queryParam = queryParam;
			}
			if (timeout) {
				state.apiTimeout = timeout;
			}
			state.isAllChecked = false;
			zhGrid.value.clearCheckboxReserve();
			zhGrid.value.clearCheckboxRow();
			zhGrid.value.clearCurrentRow();
			zhGrid.value.clearSelected();
			zhGrid.value.clearRadioRow();
			zhGrid.value.clearRadioReserve();
			state.selectRecords = [];
			state.count = 0;
			const table = findTableList();
			setTimeout(() => {
				that.refs.zhGrid?.scrollTo(0, 0);
			}, 100);
			return table;
		}
		function refresh(queryParam: any) {
			if (queryParam) {
				state.queryParam = queryParam;
			}
			state.isAllChecked = false;
			zhGrid.value.clearCheckboxRow();
			zhGrid.value.clearCheckboxReserve();
			zhGrid.value.clearCurrentRow();
			zhGrid.value.clearSelected();
			zhGrid.value.clearRadioRow();
			zhGrid.value.clearRadioReserve();
			state.selectRecords = [];
			state.count = 0;
			findTableList();
		}
		function updateRow(row: any) {
			const data = [...state.tableData];
			let rowId = props.rowId || props.rowConfig.keyField;
			data.forEach((item, index, arr: any[]) => {
				if (item[rowId] === row[rowId]) {
					arr.splice(index, 1, reactive(row));
					return item;
				}
			});
			state.tableData = data;
		}
		function setTableList() {
			return new Promise((resolve) => {
				state.tablePage.total = state.allData.length;
				state.tableData = state.allData.slice(
					(state.tablePage.currentPage - 1) * state.tablePage.pageSize,
					state.tablePage.currentPage * state.tablePage.pageSize
				);
				resolve(state);
			});
		}
		function findTableList() {
			return new Promise((resolve) => {
				state.loading = true;
				let params = state.queryParam as any;
				if (props.type === 'paging') {
					params = Object.assign(params, state.tablePage);
				}
				params.orderVOList = state.orderList;
				let url = '';
				let config: any = {};
				if (state.apiTimeout && state.apiTimeout > 0) {
					config.timeout = state.apiTimeout;
				}
				let headers = {} as any;
				headers.cryptoEnabled = props.cryptoEnabled;
				headers.repeatEnabled = props.repeatEnabled;
				headers['x-desensitize-flag'] = props.desensitizeFlag;
				if (props.funcCode) {
					headers['func-code'] = props.funcCode;
					url = $api.common.send.url + props.funcCode;
				} else {
					url = props.url;
				}
				config.headers = headers;
				$http
					.post(url, params, config)
					.then((res: any) => {
						let data = [];
						if (props.type === 'paging') {
							data = res.result.list || [];
						} else {
							if (res.result) {
								if (res.result.list) {
									data = res.result.list || [];
								} else {
									data = res.result || [];
								}
							} else {
								data = [];
							}
						}
						state.count = 0;
						state.tableData = data;
						state.tablePage.total = Number(res.result.total);
						state.tablePage.pageNum = res.result.pageNum;
						state.tablePage.currentPage = res.result.pageNum;
						state.tablePage.pageSize = res.result.pageSize;
						state.loading = false;
						if (data && data.length > 0) {
							setDisabledList();
							resolve(state);
						} else {
							if (res.result.pageNum > 1) {
								params.pageNum = res.result.pages;
								state.loading = true;
								$http
									.post(url, params, config)
									.then((res: any) => {
										state.tableData = res.result.list || [];
										state.tablePage.total = res.result.total;
										state.tablePage.pageNum = res.result.pageNum;
										state.tablePage.currentPage = res.result.pageNum;
										state.tablePage.pageSize = res.result.pageSize;
										state.loading = false;
										setDisabledList();
										resolve(state);
									})
									.catch(() => {
										state.loading = false;
										resolve(state);
									});
							} else {
								resolve(state);
							}
						}
					})
					.catch(() => {
						state.loading = false;
						resolve(state);
					});
			});
		}
		function activeRowMethod({ row }: any) {
			if (row.disabled) {
				return false;
			} else {
				if (row.editDisabled) {
					return false;
				} else {
					return true;
				}
			}
		}
		function changeAllEvent() {
			zhGrid.value.setAllCheckboxRow(state.isAllChecked);
			if (!state.isAllChecked) {
				zhGrid.value.clearCheckboxRow();
				zhGrid.value.clearCheckboxReserve();
			}
			if (state.isAllChecked) {
				state.count = state.tablePage.total;
			} else {
				state.count = 0;
			}
		}

		function sortChange(data: any) {
			if (data.order != null) {
				let item = {} as any;
				item.property = data.property;
				item.order = data.order;
				state.orderList = state.orderList.filter((item: any) => {
					return item.property != data.property;
				});
				state.orderList.unshift(item);
			} else {
				state.orderList = state.orderList.filter((item: any) => {
					return item.property != data.property;
				});
			}
			if (props.type === 'paging') {
				state.queryParam.orderVOList = state.orderList;
				query(state.queryParam, props.timeout);
			}

			context.emit('sort-change', data);
			context.emit('sort-change-c', state.orderList);
		}
		function checkboxChange(data: any) {
			setSelectRecords();
			context.emit('checkbox-change', data);
		}
		function cellDblclick({ row, rowIndex }) {
			context.emit('cell-dblclick', { row, rowIndex });
		}
		function checkboxAll(data: any) {
			setSelectRecords();
			context.emit('checkbox-all', data);
		}
		function setSelectRecords() {
			let list: any = [];
			let thisChecked = zhGrid.value.getCheckboxRecords();
			if (!thisChecked) {
				thisChecked = [];
			} else {
				thisChecked.forEach((item: any) => {
					list.push(item);
				});
			}
			let selectReserveRecords = zhGrid.value.getCheckboxReserveRecords();
			if (!selectReserveRecords) {
				selectReserveRecords = [];
			} else {
				selectReserveRecords.forEach((item: any) => {
					list.push(item);
				});
			}

			state.selectRecords = list;
			state.count = list.length;
		}
		function onCheckMethod({ row }: any) {
			return !row.disabled;
		}

		//获取所有勾选的数据，包括当前页和其他页
		function getAllCheckboxRecords() {
			return state.selectRecords;
		}
		//用于 type=checkbox，手动清空用户的选择
		function clearCheckboxRow() {
			zhGrid.value.clearCheckboxRow();
			setSelectRecords();
		}
		function clearRadioRow() {
			zhGrid.value.clearRadioRow();
		}
		//用于 checkbox-config.reserve，手动清空用户保留选中的行数据
		function clearCheckboxReserve() {
			zhGrid.value.clearCheckboxReserve();
			setSelectRecords();
		}
		//清空数据
		function clearData() {
			state.tableData = [];
			zhGrid.value.clearCheckboxRow();
			zhGrid.value.clearCheckboxReserve();
			zhGrid.value.clearCurrentRow();
			zhGrid.value.clearSelected();
			zhGrid.value.clearRadioRow();
			zhGrid.value.clearRadioReserve();
			state.selectRecords = [];
			state.count = 0;
		}
		function exportData(filename: any, type: any) {
			if (!filename) {
				filename = '导出';
			}
			if (!type) {
				type = 'xlsx';
			}
			zhGrid.value.exportData({
				filename: filename,
				sheetName: 'Sheet1',
				type: type,
			});
		}
		const zhGridMethods: any = extendTableMethods(zhGrid);

		let sortable1: any;
		const rowDrop = () => {
			const $grid = zhGrid.value;
			sortable1 = Sortable.create($grid.$el.querySelector('.body--wrapper>.vxe-table--body tbody') as HTMLElement, {
				handle: '.table-drag-btn',
				onEnd: (sortableEvent) => {
					const targetTrElem = sortableEvent.item;
					const oldIndex = sortableEvent.oldIndex as number;
					const options = { children: 'children' };
					const wrapperElem = targetTrElem.parentNode as HTMLElement;
					const prevTrElem = targetTrElem.previousElementSibling as HTMLElement;
					const tableTreeData = [...state.tableData] as any[];
					const targetRowNode = $grid.getRowNode(targetTrElem);
					if (!targetRowNode) {
						return;
					}
					//当前节点
					const selfRow = targetRowNode.item;
					const selfNode = XEUtils.findTree(tableTreeData, (row) => row === selfRow, options);
					if (prevTrElem) {
						// 移动到目标节点
						const prevRowNode = $grid.getRowNode(prevTrElem);
						if (!prevRowNode) {
							return;
						}
						const prevRow = prevRowNode.item;

						const prevNode = XEUtils.findTree(tableTreeData, (row) => row === prevRow, options);
						if (XEUtils.findTree(selfRow[options.children], (row) => prevRow === row, options)) {
							// 错误的移动
							const oldTrElem = wrapperElem.children[oldIndex];
							wrapperElem.insertBefore(targetTrElem, oldTrElem);
							return VXETable.modal.message({ content: '不允许自己给自己拖动！', status: 'error' });
						}
						const currRow = selfNode.items.splice(selfNode.index, 1)[0];
						if ($grid.isTreeExpandByRow(prevRow)) {
							// 移动到当前的子节点
							prevRow[options.children].splice(0, 0, currRow);
						} else {
							// 移动到相邻节点
							prevNode.items.splice(prevNode.index + (selfNode.index < prevNode.index ? 0 : 1), 0, currRow);
						}
					} else {
						// 移动到第一行
						const currRow = selfNode.items.splice(selfNode.index, 1)[0];
						tableTreeData.unshift(currRow);
					}
					// 如果变动了树层级，需要刷新数据
					state.tableData = tableTreeData;
					context.emit('row-drag-change', targetRowNode, tableTreeData);
				},
			});
		};

		let initTime: any;
		nextTick(() => {
			// 加载完成之后在绑定拖动事件
			initTime = setTimeout(() => {
				rowDrop();
			}, 500);
		});

		onUnmounted(() => {
			clearTimeout(initTime);
			if (sortable1) {
				sortable1.destroy();
			}
		});

		return {
			...toRefs(state),
			rowDrop,
			clearCheckboxRow,
			setData,
			setTableData,
			checkboxAll,
			checkboxChange,
      cellDblclick,
			sortChange,
			handlePageChange,
			query,
			refresh,
			updateRow,
			activeRowMethod,
			changeAllEvent,
			getAllCheckboxRecords,
			clearCheckboxReserve,
			clearRadioRow,
			exportData,
			clearData,
			...zhGridMethods,
			zhGrid,
			attrs,
			allCheckboxConfig,
			allRadioConfig,
			fontSize,
		};
	},
});
</script>
<style lang="scss">
.table-drag-btn {
}
.card-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
}
.page-left {
	position: absolute;
	left: 10px;
	top: 50%;
	transform: translateY(-50%);
	z-index: 10;
}
.vxe-table--render-default.size--small {
	font-size: 14px;
}
.vxe-pager.size--small {
	font-size: 14px;
}
.vxe-grid.size--small {
	font-size: 14px;
}
.vxe-select--panel.size--small,
.vxe-select.size--small {
	font-size: 14px;
}
.vxe-input.size--small {
	font-size: 14px;
}
.vxe-table--render-default .vxe-body--row.row--current {
	background-color: var(--el-color-primary-light-9) !important;
	color: var(--el-color-primary);
}
.vxe-table--render-default .vxe-body--row.row--hover {
	background-color: var(--el-color-primary-light-8) !important;
}

.vxe-table--render-default .vxe-body--row.row--above {
	background-color: #cef1dc !important;
}
.vxe-table--render-default .vxe-body--row.row--beyond {
	background-color: #e7b9b9 !important;
}

.vxe-table--render-default .vxe-table--border-line {
	border-style: none;
	border-bottom: 1px solid var(--el-card-border-color);
}

.vxe-table--render-default .vxe-header--column.col--current {
	background-color: var(--el-color-primary-light-8) !important;
}
.vxe-table--render-default .vxe-body--column.col--current {
	background-color: var(--el-color-primary-light-8) !important;
}
.vxe-table--render-default .vxe-footer--column.col--current {
	background-color: var(--el-color-primary-light-8) !important;
}
.vxe-primary-color {
	color: var(--el-color-primary);
}
.vxe-table--render-default .vxe-body--row.row--stripe {
	background-color: var(--el-disabled-bg-color);
}
.vxe-table--render-default .vxe-body--row.row--radio {
	color: var(--el-color-primary);
	background-color: #fff3e0;
}
.vxe-table--render-default .vxe-body--row.row--checked {
	color: var(--el-color-primary);
	background-color: #fff3e0;
}
.vxe-table--render-default .is--checked.vxe-cell--radio {
	color: var(--el-color-primary);
}
.vxe-table--render-default .is--checked.vxe-cell--radio .vxe-radio--checked-icon:before {
	border-color: var(--el-color-primary);
	background-color: var(--el-color-primary);
}
.vxe-table--render-default .vxe-cell--radio:not(.is--disabled):hover .vxe-radio--icon:before {
	border-color: var(--el-color-primary);
}
.vxe-table--render-default .is--checked.vxe-cell--checkbox,
.vxe-table--render-default .is--indeterminate.vxe-cell--checkbox {
	color: var(--el-color-primary);
}
.vxe-table--render-default .is--checked.vxe-cell--checkbox .vxe-checkbox--icon:before,
.vxe-table--render-default .is--indeterminate.vxe-cell--checkbox .vxe-checkbox--icon:before {
	border-color: var(--el-color-primary);
}
.vxe-table--render-default .vxe-cell--checkbox:not(.is--disabled):hover .vxe-checkbox--icon:before {
	border-color: var(--el-color-primary);
}
</style>
